# Using Immer

import index from '!!raw-loader!@site/docs/examples/immer.ex';
import { LiveDemo } from '@site/components/LiveDemo';

When working with immutable objects, we often get to what’s called a “spread hell” situation. If you prefer working with immutable objects in a mutable fashion, you can use immer with Elf.

Create a mutation function:

```ts title="store/mutations.ts"
import { produce } from 'immer';

export function write<S>(updater: (state: S) => void): (state: S) => S {
  return function (state) {
    return produce(state, (draft) => {
      updater(draft as S);
    });
  };
}
```

Now you can use it in the store's `update` function:

```ts title="todos.respository.ts"
import { withProps, createStore } from '@ngneat/elf';
import {
  withEntities,
  selectAllEntities,
  updateEntities,
} from '@ngneat/elf-entities';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

export interface TodosProps {
  filter: 'ALL' | 'ACTIVE' | 'COMPLETED';
}

const store = createStore(
  { name: 'todos' },
  withEntities<Todo>(),
  withProps<TodosProps>({ filter: 'ALL' }),
);

export const todos$ = store.pipe(selectAllEntities());

export function updateFilter(filter: TodosProps['filter']) {
  store.update(
    // highlight-start
    write((state) => {
      state.filter = filter;
    }),
    // highlight-end
  );
}

export function updateCompleted(id: Todo['id']) {
  store.update(
    updateEntities(
      id,
      // highlight-next-line
      write<Todo>((entity) => (entity.completed = !entity.completed)),
    ),
  );
}
```

<LiveDemo src={index} packages={['entities', 'immer']} />
